/*
 * Copyright 2007 Agile Plugins Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * 	http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.googlecode.agileplugins.monkey;

import com.intellij.codeInsight.template.TemplateManager;
import com.intellij.codeInsight.template.impl.TemplateContext;
import com.intellij.codeInsight.template.impl.TemplateImpl;
import com.intellij.codeInsight.template.impl.TemplateSettings;
import com.intellij.ide.todo.TodoConfiguration;
import com.intellij.ide.todo.TodoFilter;
import com.intellij.ide.todo.TodoView;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.DataConstants;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vcs.VcsConfiguration;
import com.intellij.psi.search.TodoAttributes;
import com.intellij.psi.search.TodoPattern;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Pattern;

public class ChangeCardAction extends AnAction {
    private static final String BLAH = "Blah";
    protected Logger logger = Logger.getInstance(getClass().getName());

    public void actionPerformed(AnActionEvent anActionEvent) {
        DataContext datacontext = anActionEvent.getDataContext();
        Project project = (Project) datacontext.getData(DataConstants.PROJECT);
        TextFieldDialog dialog = new TextFieldDialog("Change Storycard", "Please type the new Storycard ID", project);
        dialog.setText(VcsConfiguration.getInstance(project).getLastNonEmptyCommitMessage());
        dialog.show();
        if (dialog.isOK()) {
            String story = dialog.getText();
            if (story != null) {
                story = story.trim();
                if (story.length() > 0) {
                    setUpCvs(story, project);
                    setUpLiveTemplates(story, project);
                    setUpTodos(story, project);
                }
            }
        }
    }

    private void setUpCvs(String story, Project project) {
        VcsConfiguration instance = VcsConfiguration.getInstance(project);
        instance.saveCommitMessage(story);
    }

    private void setUpTodos(String story, Project project) {
//        setUpTodoView(story, project);
        updateTodos(story, project);

    }

    private void setUpTodoView(String story, Project project) {
        try {
            TodoView todoView = (TodoView) project.getComponent(TodoView.class);
            setUpView(todoView, story, "h");
            setUpView(todoView, story, "i");
        } catch (Exception e) {
            logger.error("Can't mess with TodoView: " + e);
        }
    }

    private void setUpView(TodoView todoView, String story, String fieldName) throws NoSuchFieldException, IllegalAccessException {
        Field field = todoView.getClass().getDeclaredField(fieldName);
        field.setAccessible(true);
        Object settings = field.get(todoView);
        Field selectedTodoFilter = settings.getClass().getDeclaredField("e");
        selectedTodoFilter.setAccessible(true);
        selectedTodoFilter.set(settings, story);
    }

    private void updateTodos(String story, Project project) {
        TodoConfiguration todo = TodoConfiguration.getInstance();
        TodoPattern[] todoPatterns = todo.getTodoPatterns();
        TodoPattern existingPattern = null;
        int existingPatternIndex = todoPatterns.length;
        for (int i = 0; i < todoPatterns.length; i++) {
            TodoPattern todoPattern = todoPatterns[i];
            Pattern pattern = todoPattern.getPattern();
            if (pattern.pattern().startsWith("\\bFIX ")) {
                existingPatternIndex = i;
                existingPattern = todoPattern;
                break;
            }
        }
        int length = Math.max(existingPatternIndex + 1, todoPatterns.length);
        final TodoPattern[] newPatterns = new TodoPattern[length];
        System.arraycopy(todoPatterns, 0, newPatterns, 0, todoPatterns.length);
        TodoPattern newPattern = new TodoPattern("\\bFIX " + story + "\\b.*", TodoAttributes.createDefault(), false);

        newPatterns[existingPatternIndex] = newPattern;

        TodoFilter[] todoFilters = todo.getTodoFilters();
        List list = new ArrayList();
        for (int i = 0; i < todoFilters.length; i++) {
            TodoFilter todoFilter = todoFilters[i];
            if (todoFilter.contains(existingPattern)) {
                todoFilter.removeTodoPattern(existingPattern);
            }
            if (!todoFilter.isEmpty()) {
                list.add(todoFilter);
            }
        }
        TodoFilter filter = new TodoFilter();
        filter.setName(story);
        filter.addTodoPattern(newPattern);
        list.add(filter);
        final TodoFilter[] newFilters = (TodoFilter[]) list.toArray(new TodoFilter[0]);

        todo.setTodoPatterns(newPatterns);

        setUpTodoView(story, project);

        todo.setTodoFilters(newFilters);

    }

    private void setUpLiveTemplates(String story, Project project) {
        TemplateSettings templateSettings = TemplateSettings.getInstance();

        TemplateManager manager = TemplateManager.getInstance(project);
        TemplateImpl codeTemplate = (TemplateImpl) manager.createTemplate("j", "user", "// FIX " + story + " ");
        codeTemplate.setDescription("Insert a Java fix comment for " + story + ".");
        templateSettings.addTemplate(codeTemplate);
        TemplateImpl xmlTemplate = (TemplateImpl) manager.createTemplate("x", "user", "<!-- FIX " + story + " $COMMENT$ -->");
        xmlTemplate.addVariable("COMMENT", "", "", true);
        xmlTemplate.parseSegments();
        xmlTemplate.setDescription("Insert a XML fix comment for " + story + ".");
        TemplateContext templateContext = xmlTemplate.getTemplateContext();
        templateContext.JAVA_CODE = false;
        templateContext.XML = true;
        templateSettings.addTemplate(xmlTemplate);
    }
}
